/*
 * @Author: 陈明烽
 * @FilePath: \evdata\src\DatePickerRangeTime\index.tsx
 * @Description: 控制的范围的日期时间选择组件，对RangePicker再次封装
 */

import * as React from 'react';
import { useState, useEffect, FC, useCallback, useMemo } from 'react';
import { DatePicker } from 'antd';
import moment, { Moment } from 'moment';
// import  'moment/locale/zh-cn'
import { RangePickerProps } from 'antd/lib/date-picker';
// moment.locale('zh-CN')
const { RangePicker } = DatePicker;
export type EventValue<DateType> = DateType | null;
export type RangeValue<DateType> =
  | [EventValue<DateType>, EventValue<DateType>]
  | null;

export type DisabledTimes = {
  disabledHours?: () => number[];
  disabledMinutes?: (hour: number) => number[];
  disabledSeconds?: (hour: number, minute: number) => number[];
};
export type DatePickerRangeTimeProps = {
  /**Form.Item 赋值 */
  value?: [string, string] | [] | [Moment, Moment];
  /**不能选择的时间 开始 可以传 2021-06-11 15:26:31 如果时间有时分秒则要转antd RangePicker组件的 showTime */
  disableStartDate?: Moment | string;
  /**不能选择的时间 结束 可以传 2021-06-21 05:13:48 */
  disableEndDate?: Moment | string;
  /**选中日期之后触发 */
  onChange?: (val: [Moment, Moment], formatString: [string, string]) => void;
} & Omit<RangePickerProps, 'onChange' | 'value'>;

function range(start: number, end: number) {
  const result = [];
  for (let i = start; i < end; i++) {
    result.push(i);
  }
  return result;
}

/**
 * @description: 将时间转换成YYYY-MM-DD的Moment
 * @param {Moment} m
 * @return {*}
 */
const getYYYYMMDD = (m: Moment) => {
  return moment(m.format('YYYY-MM-DD'));
};

const DatePickerRangeTime: FC<DatePickerRangeTimeProps> = props => {
  const {
    onChange,
    value,
    disableEndDate,
    disableStartDate,
    ...restProps
  } = props;
  /**储存待选日期 */
  const [dates, setDates] = useState<
    RangeValue<Moment> | [] | [Moment, Moment]
  >([]);
  /**储存真正的选择的日期 */
  const [relValue, setRelValue] = useState<
    RangeValue<Moment> | [Moment, Moment] | undefined
  >();
  /**临时储存的空日期或者undefined 用来日期组件激活的时候清除之前选择的日期 */
  const [hackValue, setHackValue] = useState<
    RangeValue<Moment> | [Moment, Moment]
  >();

  /**不可选择的日期 */
  const disabledDate = useCallback(
    (current: Moment) => {
      if (!disableEndDate && !disableStartDate) {
        return false;
      }
      let res = false;
      //当前时间转成YYYY-MM-DD
      let cDatc = getYYYYMMDD(current);
      if (disableStartDate) {
        let sData =
          typeof disableStartDate === 'string'
            ? getYYYYMMDD(moment(disableStartDate))
            : getYYYYMMDD(disableStartDate);
        if (cDatc < sData) {
          res = true;
        }
      }
      if (disableEndDate) {
        let eData =
          typeof disableEndDate === 'string'
            ? getYYYYMMDD(moment(disableEndDate))
            : getYYYYMMDD(disableEndDate);
        if (cDatc > eData) {
          res = true;
        }
      }

      return res;
    },
    [dates, disableEndDate, disableStartDate],
  );
  /**不可选择的时间 */
  const disabledRangeTime = useCallback(
    (current: EventValue<Moment>, type: 'start' | 'end') => {
      if (!disableEndDate && !disableStartDate) {
        return {};
      }
      let res: DisabledTimes = {};

      if (disableStartDate) {
        /**可以选择的时间范围开始时间 */
        let sData =
          typeof disableStartDate === 'string'
            ? moment(disableStartDate)
            : disableStartDate;
        /**开始时间 小时 */
        let HH = sData.hours();
        /**开始时间 分钟 */
        let MM = sData.minutes();
        /**开始时间 秒 */
        let SS = sData.seconds();
        /** 并且 选择的是开始时间当天 */
        if (current?.format('YYYY-MM-DD') === sData.format('YYYY-MM-DD')) {
          /**把0到HH小时设置为不可选择 */
          res.disabledHours = () => range(0, HH);
          if (current?.hours() === HH) {
            /**选择的是开始时间的小时 */
            res.disabledMinutes = () => range(0, MM);
            if (current?.minutes() === MM) {
              /**选择的是开始时间的分钟 */
              res.disabledSeconds = () => range(0, SS);
            }
          }
        }
      }
      if (disableEndDate) {
        /**可以选择的时间范围结束时间 */
        let eData =
          typeof disableEndDate === 'string'
            ? moment(disableEndDate)
            : disableEndDate;
        /**结束时间 小时 */
        let HH = eData.hours();
        /**结束时间 分钟 */
        let MM = eData.minutes();
        /**结束时间 秒 */
        let SS = eData.seconds();
        /** 并且 选择的是结束时间当天 */
        if (current?.format('YYYY-MM-DD') === eData.format('YYYY-MM-DD')) {
          /**把0到HH小时设置为不可选择 */
          res.disabledHours = () => range(HH + 1, 24);
          if (current?.hours() === HH) {
            /**选择的是结束时间的小时 */
            res.disabledMinutes = () => range(MM + 1, 60);
            if (current?.minutes() === MM) {
              /**选择的是结束时间的分钟 */
              res.disabledSeconds = () => range(SS + 1, 60);
            }
          }
        }
      }
      return res;
    },
    [disableEndDate, disableStartDate],
  );

  /**真正的日期选择后触发的函数 */
  const handleChange = (
    val: RangeValue<Moment>,
    formatString: [string, string],
  ) => {
    setRelValue(val);
    if (val) {
      onChange && onChange([val[0] as Moment, val[1] as Moment], formatString);
    }
  };
  /**弹出日历和关闭日历的回调 */
  const onOpenChange = (open: boolean) => {
    if (open) {
      // @ts-ignore：无法被执行的代码的错误
      setHackValue([]);
      setDates([]);
    } else {
      setHackValue(undefined);
    }
  };

  useEffect(() => {
    if (value?.length && value.length > 0) {
      if (typeof value[0] === 'string' && typeof value[1] === 'string') {
        setRelValue([moment(value[0]), moment(value[1])]);
      } else {
        setRelValue([value[0] as Moment, value[1] as Moment]);
      }
    } else {
      setRelValue(undefined);
    }
    // setrelValue(value);
  }, [value]);

  return (
    <>
      <RangePicker
        {...restProps}
        /**优先使用假日期，再使用真日期 */
        value={hackValue || relValue}
        disabledDate={disabledDate}
        disabledTime={disabledRangeTime}
        /**待选日期发生变化的回调 */
        onCalendarChange={val => setDates(val)}
        onChange={handleChange}
        onOpenChange={onOpenChange}
      />
    </>
  );
};
export default DatePickerRangeTime;
